package humanMirror.model.controller;

/**
 * Controller class is used to out questions, recommendations and for transfer
 * entered information
 *
 * @version 1 10 jun 2012
 * @author Lyuda
 */


import humanMirror.model.accumulator.Accumulator;
import humanMirror.model.advisor.AdvancedAdvisor;
import humanMirror.model.advisor.OrganAdvisor;
import humanMirror.model.analyzer.Consultation;
import humanMirror.model.human.Human;
import humanMirror.model.human.OrganInfo;
import humanMirror.model.human.SomeConstants;
import humanMirror.model.questionLibrary.QuestionInfo;
import humanMirror.model.questionLibrary.QuestionLibrary;
import humanMirror.model.questionLibrary.SqlWorker;

import java.util.ArrayList;
import java.util.List;


public class Controller implements ControllerInterface {

    private Human pokemon;
    private AdvancedAdvisor consultant;
    private QuestionLibrary questionLibrary;
    private QuestionInfo question;
    private Accumulator accumulator;
    private OrganInfo organEffect;
    private InputOutputInterface information;
    int countOfQuestions;

    public Controller(Human pokemon, InputOutputInterface information) {
        this.pokemon = pokemon;
        questionLibrary = new QuestionLibrary(new SqlWorker());
        accumulator = new Accumulator();
        consultant = new AdvancedAdvisor(pokemon);
        //consultant = new AdvancedAdvisor(this.pokemon);
        consultant.addAdvisors(new OrganAdvisor(this.pokemon, SomeConstants.Organs.BRAIN.getOrganNumber()));
        consultant.addAdvisors(new OrganAdvisor(this.pokemon, SomeConstants.Organs.LIVER.getOrganNumber()));
        this.information = information;
        countOfQuestions = questionLibrary.getCountOfQuestions();
    }

    public Controller(Human pokemon) {
        this(pokemon, new HandlerInputOutput());
    }

    public void outputQuestions() {
        int[] answers;
        for (int numberOfQuestion = 0; numberOfQuestion < questionLibrary.getCountOfQuestions(); numberOfQuestion++)
        {
            answers = null;
            question = questionLibrary.getQuestion(numberOfQuestion);
            information.print(question.toString());
            while (answers == null) {
                try {
                    answers = information.readAnswer();
                } catch (NumberFormatException ex) {
                    information.print("В вашем ответете должны быть только цыфры!\nПовторите ответ.");
                }
            }
            organEffect = countEffect(answers);
            accumulator.addInfo(organEffect);
        }
        influence();
    }

    /**
     * used for setting up
     * all changes happened to pokemon
     * and to close the database connection
     */
    private void influence() {
        accumulator.pokemonInfluence(pokemon);
        questionLibrary.disconnect();
    }

    /**
     * calculates the result and outputs it
     * to console
     */
    public void getRecommendation() {
        try {
            consultant.performConsultation();
            information.print(consultant.getHumanConsultation());
            List<Consultation> consultations = consultant.getConsultations();
            for (Consultation consultation : consultations) {
                information.print(consultation.organHealth() + " ");
                information.print(consultation.organParameters());
            }
        } catch (Exception ex) {
            information.print("Problem in getRecommendation. It throws exception: " + ex);
        }
    }

    private OrganInfo countEffect(int[] answers) {
        OrganInfo result = new OrganInfo();
        for (int numberOfOrgan = 0; numberOfOrgan < SomeConstants.COUNT_OF_ORGANS; numberOfOrgan++) {
            for (int numberOfParam = 0; numberOfParam < SomeConstants.MAX_COUNT_OF_PARAMS; numberOfParam++) {
                result.setParameter(numberOfOrgan, numberOfParam, question.getEffect(numberOfOrgan, numberOfParam, answers));
            }
        }
        return result;
    }

    /**
     * sets current question by number
     * numeration starts from 0
     */
    public String getQuestion(int questionNumber) {
        question = questionLibrary.getQuestion(questionNumber);
        return question.getQuestion();
    }


    public String[] getAnswers()  {
        return question.getAnswers();
    }


    public void setAnswers(int... answers) {
        organEffect = countEffect(answers);
        accumulator.addInfo(organEffect);
    }


    public void stopAsking() {
        influence();
    }

    /**
     * returns an array of answers
     *
     * @return  array of String Recommendations
     */
    public String[] getRecommendationArray() {
        List<String> sb = new ArrayList<String>();
        try {
            consultant.performConsultation();
            List<Consultation> consultations = consultant.getConsultations();

            for (Consultation consultation : consultations) {
                sb.add(consultation.organHealth());
            }

        } catch (Exception ex) {
            sb.add(ex.getMessage());
        }
        return sb.toArray(new String[sb.size()]);
    }


    public int getCountOfQuestions() {
        return questionLibrary.getCountOfQuestions();
    }
}